// 用户模块
/*----------依赖模块--------- */
const express = require('express');
const router = express.Router();
const db = require('../db/db');
const back = require('../utils/back');
const md5 = require('md5');
const middle = require('../middle/auth');
const dayjs = require('dayjs');
const token = require('../controller/token');
/*----------API方法---------- */
// 所有的user方法都存到这个对象中
const user = {};
// 检查数据库中是否存在user表，创建表user
// 用户注册
user.register = async (req, res) => {
  // 用户数据通过post方法都传参
  const params = req.body;
  console.log(params);
  /* 错误处理（部分），前端给的东西要验证
  数据库要求传入的参数：
  params.name  params.sex params.age params.mobile params.password
  */
  // 参数是否齐全
  if (!params.name || !params.password || !params.age || !params.phone_number) {
    // 如果参数不全，要返回给客户端一个内容
    res.send(back.ERR(back.ERRTYPE.ERROR_PARAM, '注册的参数不全'))
    return;
  }
  // 验证手机号是不是已经存在，要查询数据库user
  const hasMobile = await db.query('select * from user where phone_number = ?', [params.phone_number]);
  // 如sql错
  if (hasMobile === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '查询失败'));
    return;
  }
  //  判断手机号
  if (hasMobile.length > 0) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '手机号冲突'));
    return;
  }
  // 对时间格式进行处理
  const d = params.time ? dayjs(params.time) : dayjs();
  const register_time = d.format('YYYY-MM-DD HH:mm:ss');
  console.log(register_time);

  // 插入新的数据
  const state = await db.query('insert into user (avatar,username,password,phone_number,register_time,age) values (?,?,?,?,?,?)',
    ['/images/user/default_userhead.png', params.name, md5(params.password), params.phone_number, register_time, params.age]);
  console.log(state);
  // 如sql错了怎么办
  if (state === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '插入失败'));
    return;
  }
  // 响应
  res.send(back.State('注册成功'))
  return;
}
// 用户列表
user.player = async (req, res) => {
  // 查询数据库user表，name,sex,head,login_time
  const dataList = await db.query('select username,avatar,login_time from user');
  // 错误处理
  if (dataList === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '查询失败'));
    return;
  }
  // 响应
  res.send(back.Data(dataList));
  return;
}
// 登录
user.login = async (req, res) => {
  const params = req.body;
  if (!params.phone_number || !params.password) {
    res.send(back.ERR(back.ERRTYPE.ERROR_PARAM, '手机号或密码为空'));
    return;
  }
  const userInfo = await db.query('select * from user where phone_number =?', [params.phone_number]);
  if (userInfo === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '查询失败'));
    return;
  }
  // 没查到
  if (!userInfo.length) {
    res.send(back.ERR(back.ERRTYPE.ERROR_VALI, '手机号未注册'));
    return;
  }
  // 查到了且长度为1，就可以查询密码是否正确了 
  if (userInfo[0].password !== md5(params.password)) {
    res.send(back.ERR(back.ERRTYPE.ERROR_PARAM, '密码错误'));
    return;
  }
  // const hasPassword = await db.query('select name from user where mobile =?',[md5(params.password)]);
  // token 生成

  const tokenState = await token.New('用户', userInfo[0].user_id, userInfo[0].username);
  // 如果生成token的过程出错，会提示错误信息
  if (tokenState.err == 1) {
    res.send(back.ERR(back.ERRTYPE.ERROR_PARAM, "token错误"))
    return
  }
  const d = params.time ? dayjs(params.time) : dayjs();
  const login_time = d.format('YYYY-MM-DD HH:mm:ss');

  const state = await db.query(`update user set login_time=? where user_id=?`, [login_time, userInfo[0].user_id])
  if (state === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '更新失败'));
    return;
  }
  // 如果想拿到登陆时间，在进行一次查询
  userInfo[0].login_time = login_time;
  // 密码删掉之后再给前端返回
  delete userInfo[0].password;
  // 打一个数据包当作返回值
  const data = {
    user: userInfo[0],
    token: tokenState.key
  }
  res.send(back.Data(data))
  return;
}

// 修改信息
user.edit = async (req, res) => {
  const params = req.body;
  const { user_id } = req.userInfo;
  // 允许修改的字段
  const updateFields = ['avatar', 'name', 'phone_number', 'password', 'age',];
  console.log(user_id);

  // 创建一个空对象，这个对象存储需要更改的属性字段以及值
  const updatedParams = {};
  // 用遍历的方法把参数中有值的，还要对应可以修改的字段重复的部分单独取出来放到updatedParams中形成一个新的对象
  updateFields.forEach(i => {
    // 如果有值，就放到updatedParams 中
    if (params[i]) {
      updatedParams[i] = params[i];
    }
  });
  // console.log(updatedParams);
  // 构建更新SQL语句
  const buildUpdateSql = (updatedParams) => {
    // 过滤掉id并获取其它需要更新的键 ，如果后期id来自token，就不需要排除了
    // const keysToUpdateArr = Object.keys(updatedParams).filter(key => {
    // 	return key !== 'id'
    // });
    // 获取需要更新的键
    const keysToUpdateArr = Object.keys(updatedParams);
    // console.log(keysToUpdateArr);//[ 'mobile' ]
    // 不破坏原始对象，创建一个新数组在这个增加的数组里进行，数组存储的是mobile=?
    let setSQL = [];
    // 存储的是参数值 ，[ '18500000001', 2 ] 最后一个是id
    let setParams = [];
    // 遍历每一个参数传递来的key字段
    keysToUpdateArr.forEach(key => {
      if (key === 'password') {
        // 对password字段使用MD5加密  
        setSQL.push(`password=md5(?)`);
        setParams.push(updatedParams[key]);
      } else {
        setSQL.push(`${key}=?`);
        setParams.push(updatedParams[key]);
      }
    });

    // 构建SQL语句  ，多个之间用，分割，如果没有多个就没有，去分割了
    const sql = `update user set ${setSQL.join(', ')} where user_id=?`;

    // 使用concat将id添加到参数数组末尾  
    setParams = setParams.concat(user_id);

    // 返回构建好的SQL语句和参数数组  
    return { sql, setParams };
  };

  // 验证手机号是否已经存在，要查询数据库user
  const hasMobile = await db.query('select * from user where phone_number = ?', [params.phone_number],);
  if (hasMobile === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '查询失败'));
    return;
  }
  // 判断手机号是否存在
  if (hasMobile.length > 0) {
    res.send(back.ERR(back.ERRTYPE.ERROR_PARAM, '该手机号已经存在，不能更改为该手机号'));
    return;
  }

  // 修改
  const state = await db.query(buildUpdateSql(updatedParams).sql, buildUpdateSql(updatedParams).setParams);
  if (state === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '修改失败'));
    return;
  }
  // 刚修改完，新的数据客户端还没有，再查一次才能是新的
  const userInfo = await db.query('select * from user where user_id = ?', [user_id]);
  if (userInfo === false) {
    res.send(back.ERR(back.ERRTYPE.ERROR_DB, '查询失败'));
    return;
  }
  // 密码删掉之后再给前端返回
  delete userInfo[0].password;
  res.send(back.Data(userInfo[0]));
  return;
}

//图片上传应该单独做一个模块原则上不应该和某个模块合并到一块
//头像上传(用户信息修改)

/*---------路由---------- */

// 注册
router.post('/register', user.register);
// 用户列表
router.get('/player', user.player);
// 用户登陆
router.post('/login', user.login);
// 修改信息
router.post('/editinfo', middle.userAuth, user.edit);


/*-------暴露----------- */
module.exports = router;